/*
 * WorkspaceClases.cpp
 *
 *  Created on: 28/04/2013
 *      Author: juan
 */

#include "gui/SubWindow/WorkspaceClases.h"
#include "gui/VisualComponents/clases/VisualClassComponentClase.h"
#include "gui/VisualComponents/clases/VisualClassComponentVia.h"
#include "gui/VisualComponents/VisualComponentVia.h"
#include "gui/Tabs.h"
#include "xml/XmlReader.h"
#include <iostream>

using namespace std;

WorkspaceClases::WorkspaceClases(Diagram* diagram, bool enableEvents):Workspace(diagram,enableEvents)  {
}

WorkspaceClases::~WorkspaceClases() {
}

void WorkspaceClases::validateDiagram(std::string archivo){

      fstream filestr;
      filestr.open(archivo.c_str(), std::fstream::out);

        if (filestr.is_open())
            m_diagram->validateDiagram(filestr);
        filestr.close();

}

void WorkspaceClases::store(XmlWriter& writer_rep, XmlWriter& writer_comp){
    Utils utils;
    updateDiagramSize();
    writer_rep.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());
    writer_rep.addCurrentNodeProperty("type", utils.convertToString(m_diagram->getType()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_X, utils.convertToString(m_diagram->getSizeX()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_Y, utils.convertToString(m_diagram->getSizeY()).c_str());

    writer_comp.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());

    for (std::vector<VisualDiagramComponent*>::iterator it = m_visualComponentList.begin();
    		it != m_visualComponentList.end(); ++it) {
    	(*it)->store(writer_rep, writer_comp, m_diagram);
    }

}

void WorkspaceClases::store(XmlWriter& writer_rep, XmlWriter& writer_comp, std::string tabName){
    Utils utils;
    updateDiagramSize();
    writer_rep.addCurrentNodeProperty(TARGET_NAME, tabName.c_str());
    writer_rep.addCurrentNodeProperty("type", utils.convertToString(m_diagram->getType()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_X, utils.convertToString(m_diagram->getSizeX()).c_str());
    writer_rep.addCurrentNodeProperty(TARGET_SIZE_Y, utils.convertToString(m_diagram->getSizeY()).c_str());

    writer_comp.addCurrentNodeProperty(TARGET_NAME, m_diagram->getName().c_str());

    for (std::vector<VisualDiagramComponent*>::iterator it = m_visualComponentList.begin();
    		it != m_visualComponentList.end(); ++it) {
    	(*it)->store(writer_rep, writer_comp, m_diagram);
    }

}

void WorkspaceClases::on_load(XmlReader& readerModel, XmlReader & readerRep, Tabs* tabs) {

	try {
	        Utils utils;
	        //setea atributos del diagram
	        readerRep.setCurrentNode(readerRep.getRoot());
	        m_diagram->setName(readerRep.getCurrentNodeProperty(TARGET_NAME));
	        m_diagram->setSize(utils.convertToUnsigned(readerRep.getCurrentNodeProperty(TARGET_SIZE_X)),
	                utils.convertToUnsigned(readerRep.getCurrentNodeProperty(TARGET_SIZE_Y)));

	        std::map< unsigned, VisualDiagramComponent* > visualComponents;
            std::map< unsigned, std::vector<int> > idsComponentesEntradas;
            std::map< unsigned, unsigned> startFromVias;
	        const char* nameComponente;
	        xmlNode* nodoActual = NULL;
	        xmlNode* nodoAnterior = NULL;
	        if (readerRep.hasChild()) {
	        	nodoActual = readerRep.getCurrentNodeChild();
	        }


	        while ( nodoActual )
	        {
	        	readerRep.setCurrentNode(nodoActual);
	            nameComponente = readerRep.getCurrentNodeName();
	            VisualDiagramComponent* visualComponent =
	            		buildComposedComponent(nameComponente, m_diagram, readerRep, startFromVias);

	            if ( visualComponent ) {
	                visualComponent->load(readerRep, readerModel, m_diagram);
	                addVisualComponent(visualComponent);
	                //Save locally to conect components
	                int identificadorComponente = utils.convertToInt(readerRep.getCurrentNodeProperty(TARGET_ID));
	                visualComponents[identificadorComponente] = visualComponent;

	                std::vector<int> ids;
	                nodoAnterior = readerRep.getCurrentNode();
	                xmlNode* nodoActual = readerRep.getCurrentNodeChild();
	                while (nodoActual)
	                {
	                    readerRep.setCurrentNode(nodoActual);
	                    if ( strcmp(readerRep.getCurrentNodeName(), TARGET_PUNTO) != 0
	                    		&& strcmp(readerRep.getCurrentNodeName(), TARGET_OTHER_DIAGRAM) != 0 )
	                    {
	                        ids.push_back(utils.convertToInt(readerRep.getCurrentNodeProperty(TARGET_ID)));
	                    }
	                    if (readerRep.hastNextNode())
	                    	nodoActual = readerRep.nextNode();
	                    else
	                    	nodoActual = NULL;
	                }
	                idsComponentesEntradas[identificadorComponente] =  ids;
	                readerRep.setCurrentNode(nodoAnterior);
	            }

	            if (readerRep.hastNextNode()) {
	            	nodoActual = readerRep.nextNode();
	            }
	            else{
	            	nodoActual = NULL;
	            }
	        }
	        connectComponents(visualComponents, idsComponentesEntradas, startFromVias);
	    } catch (std::exception & e) {
	        throw std::runtime_error("Formato invalido del archivo xml");
	    }
}

void WorkspaceClases::connectComponents(std::map< unsigned,
		VisualDiagramComponent* > & visualComponents,
		std::map< unsigned, std::vector<int> > & idsComponentesEntradas ,
		std::map<unsigned, unsigned>& startFromVias )
{
    //Conecta los componentes
    for( unsigned i = 0; i < idsComponentesEntradas.size(); i++ )
    {
        std::vector<int> ids = idsComponentesEntradas[i];
        VisualDiagramComponent* visualComponent = visualComponents[i];
        for (unsigned j = 0; j < ids.size(); j++) {
            if ( ids[j] == -1)
                continue;
            VisualClassComponentVia* visualVia = dynamic_cast<VisualClassComponentVia*>(visualComponents[ids[j]]);
            VisualComponentConector* connector = (VisualComponentConector*) visualComponent->getChildren()[j];

            unsigned idVia = getDiagram()->getId(visualVia->getComponent());
            unsigned idVisualComponent = getDiagram()->getId(visualComponent->getComponent());

            if ( startFromVias[idVia] == idVisualComponent ) {
            	visualVia->setStartConector(connector);
            }
            else {
            	visualVia->setEndConector(connector);
            }
            connector->setVia(visualVia);
        }
    }
}

void WorkspaceClases::on_load(XmlReader& reader, Tabs* tabs) {

}

VisualDiagramComponent* WorkspaceClases::buildComposedComponent(const char* nameComponent,
		Diagram* diagram, XmlReader& reader , std::map<unsigned,unsigned>& startFromVias) {

    	if(!strcmp(nameComponent, NODE_CLASS)) {
    		VisualClassComponentClase* comp = new VisualClassComponentClase(diagram);
    		return comp;
    	}

    	if (!strcmp(nameComponent, TARGET_VIA)) {
    		Utils utils;
    		unsigned idStart = utils.convertToUnsigned(reader.getCurrentNodeProperty("idStart"));
    		unsigned viaNro = utils.convertToUnsigned(reader.getCurrentNodeProperty(TARGET_ID));
    		startFromVias[viaNro] = idStart;
    		return new VisualClassComponentVia(diagram);
    	}

    	return NULL;
    }
